package admin

import (
	"encoding/json"
	"errors"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/spf13/cast"
	"io/ioutil"
	"os"
	"outsourced-projects/config"
	"outsourced-projects/pkg/communal"
	"outsourced-projects/service"
	"strings"
	"time"
)

type Task struct {
	service.Base
}

func (task Task) TaskList(c *gin.Context) {
	var err error
	//数据获取
	jsondata := make(map[string]interface{})
	err = c.BindJSON(&jsondata)
	if err != nil {
		service.ReturnJson(c, 500, err.Error(), gin.H{})
		return
	}
	//初始化数据库
	db := communal.Sql()
	defer db.Close()

	limitstr := fmt.Sprintf(" limit %d,%d", (cast.ToInt(jsondata["page_index"])-1)*cast.ToInt(jsondata["page_size"]), cast.ToInt(jsondata["page_size"]))
	orderstr := " order by a.`id` desc"

	wheresql := strings.Builder{}

	//if cast.ToString(jsondata["type"]) != "" {
	//	wheresql.WriteString(fmt.Sprintf(" and a.`type` = '%s'", cast.ToString(jsondata["type"])))
	//}

	listsql := fmt.Sprintf("select a.`id`,a.`type`,a.`name`,a.`status`,a.`ctime`,a.`utime`,a.`file` from `task` as a where 1=1 %s %s %s", wheresql.String(), orderstr, limitstr)
	listdata, err := db.QueryString(listsql)
	if err != nil {
		service.ReturnJson(c, 500, err.Error(), gin.H{})
		return
	}

	countsql := fmt.Sprintf("select count(*) as total from `task` as a where 1=1 %s", wheresql.String())
	countdata, err := db.QueryString(countsql)
	if err != nil {
		service.ReturnJson(c, 500, err.Error(), gin.H{})
		return
	}

	service.ReturnJson(c, 200, "操作成功", gin.H{
		"list":  listdata,
		"total": cast.ToInt(countdata[0]["total"]),
	})
}

func (task Task) TaskStatisticsNotice(c *gin.Context) {
	var err error
	//数据获取
	jsondata := make(map[string]interface{})
	err = c.BindJSON(&jsondata)
	if err != nil {
		service.ReturnJson(c, 500, err.Error(), gin.H{})
		return
	}

	//初始化数据库
	db := communal.Sql()
	defer db.Close()

	data, err := db.QueryString(fmt.Sprintf("select * from `task` where `type` = 'StatisticsNotice' and `status` in (0,1)"))
	if err != nil {
		service.ReturnJson(c, 500, err.Error(), gin.H{})
		return
	}
	if len(data) > 0 {
		service.ReturnJson(c, 400, errors.New("存在待执行任务").Error(), gin.H{})
		return
	}

	datainsert := make(map[string]interface{})
	datainsert["type"] = "StatisticsNotice"
	datainsert["name"] = "考勤概括通知"
	datainsert["status"] = 0
	rawdata, _ := json.Marshal(jsondata)
	datainsert["raw"] = string(rawdata)
	datainsert["ctime"] = time.Now().Unix()
	datainsert["utime"] = time.Now().Unix()

	_, err = db.Table("task").Insert(datainsert)
	if err != nil {
		service.ReturnJson(c, 500, err.Error(), gin.H{})
		return
	}
	service.ReturnJson(c, 200, "操作成功", gin.H{})
}

func (task Task) TaskStatisticsExport(c *gin.Context) {
	var err error

	//数据获取
	jsondata := make(map[string]interface{})
	err = c.BindJSON(&jsondata)
	if err != nil {
		service.ReturnJson(c, 500, err.Error(), gin.H{})
		return
	}

	//初始化数据库
	db := communal.Sql()
	defer db.Close()

	data, err := db.QueryString(fmt.Sprintf("select * from `task` where `type` = 'StatisticsExport' and `status` in (0,1)"))
	if err != nil {
		service.ReturnJson(c, 500, err.Error(), gin.H{})
		return
	}
	if len(data) > 0 {
		service.ReturnJson(c, 400, errors.New("存在待执行任务").Error(), gin.H{})
		return
	}

	datainsert := make(map[string]interface{})
	datainsert["type"] = "StatisticsExport"
	datainsert["name"] = "考勤概括导出"
	datainsert["status"] = 0
	rawdata, _ := json.Marshal(jsondata)
	datainsert["raw"] = string(rawdata)
	datainsert["ctime"] = time.Now().Unix()
	datainsert["utime"] = time.Now().Unix()

	_, err = db.Table("task").Insert(datainsert)
	if err != nil {
		service.ReturnJson(c, 500, err.Error(), gin.H{})
		return
	}

	service.ReturnJson(c, 200, "操作成功", gin.H{})
}

func (task Task) TaskDetailedNotice(c *gin.Context) {
	var err error
	//数据获取
	jsondata := make(map[string]interface{})
	err = c.BindJSON(&jsondata)
	if err != nil {
		service.ReturnJson(c, 500, err.Error(), gin.H{})
		return
	}

	//初始化数据库
	db := communal.Sql()
	defer db.Close()

	data, err := db.QueryString(fmt.Sprintf("select * from `task` where `type` = 'DetailedNotice' and `status` in (0,1)"))
	if err != nil {
		service.ReturnJson(c, 500, err.Error(), gin.H{})
		return
	}
	if len(data) > 0 {
		service.ReturnJson(c, 400, errors.New("存在待执行任务").Error(), gin.H{})
		return
	}

	datainsert := make(map[string]interface{})
	datainsert["type"] = "DetailedNotice"
	datainsert["name"] = "考勤明细通知"
	datainsert["status"] = 0
	rawdata, _ := json.Marshal(jsondata)
	datainsert["raw"] = string(rawdata)
	datainsert["ctime"] = time.Now().Unix()
	datainsert["utime"] = time.Now().Unix()

	_, err = db.Table("task").Insert(datainsert)
	if err != nil {
		service.ReturnJson(c, 500, err.Error(), gin.H{})
		return
	}

	service.ReturnJson(c, 200, "操作成功", gin.H{})
}

func (task Task) TaskDetailedExport(c *gin.Context) {
	var err error
	//数据获取
	jsondata := make(map[string]interface{})
	err = c.BindJSON(&jsondata)
	if err != nil {
		service.ReturnJson(c, 500, err.Error(), gin.H{})
		return
	}

	//初始化数据库
	db := communal.Sql()
	defer db.Close()

	data, err := db.QueryString(fmt.Sprintf("select * from `task` where `type` = 'DetailedExport' and `status` in (0,1)"))
	if err != nil {
		service.ReturnJson(c, 500, err.Error(), gin.H{})
		return
	}
	if len(data) > 0 {
		service.ReturnJson(c, 400, errors.New("存在待执行任务").Error(), gin.H{})
		return
	}

	datainsert := make(map[string]interface{})
	datainsert["type"] = "DetailedExport"
	datainsert["name"] = "考勤明细导出"
	datainsert["status"] = 0
	rawdata, _ := json.Marshal(jsondata)
	datainsert["raw"] = string(rawdata)
	datainsert["ctime"] = time.Now().Unix()
	datainsert["utime"] = time.Now().Unix()

	_, err = db.Table("task").Insert(datainsert)
	if err != nil {
		service.ReturnJson(c, 500, err.Error(), gin.H{})
		return
	}

	service.ReturnJson(c, 200, "操作成功", gin.H{})
}

func (task Task) TaskRun(c *gin.Context) {
	var err error

	//初始化数据库
	db := communal.Sql()
	defer db.Close()

	data, err := db.QueryString(fmt.Sprintf("select * from `task` where `status` = 0"))
	if err != nil {
		service.ReturnJson(c, 500, err.Error(), gin.H{})
		return
	}
	//分支运行
	for _, v := range data {
		switch v["type"] {
		case "StatisticsNotice": //考勤概括通知
			go task.TaskTestStatisticsNotice(v["id"])
			break
		case "StatisticsExport": //考勤概括导出
			go task.TaskTestStatisticsExport(v["id"])
			break
		//case "DetailedNotice": //考勤明细通知
		//	break
		case "DetailedExport": //考勤明细导出
			go task.TaskTestDetailedExport(v["id"])
			break
		}
	}
	service.ReturnJson(c, 200, "操作成功", gin.H{})
}

//func (task Task) TaskTestStatisticsExport(id string) {
//	//unixstr := cast.ToString(time.Now().Unix())
//	//初始化数据库
//	db := communal.Sql()
//	defer db.Close()
//
//	taskdata, err := db.QueryString(fmt.Sprintf("select * from `task` where id = %s", id))
//	if err != nil {
//		return
//	}
//
//	_, err = db.Exec(fmt.Sprintf("UPDATE `task` SET `status` = 1,`utime` = UNIX_TIMESTAMP() WHERE `id` = %s", id))
//	if err != nil {
//		fmt.Println("================== status = 1 状态变更失败")
//		return
//	}
//	//c.Request.Header.Add("ExportIs", "1")
//	//c.Request.Header.Add("ExportId", id)
//
//	//创建文件
//	fileName := "StatisticsExportTemplate.xlsx"
//	sourcePath := "./" + fileName
//	// 源文件路径
//	destinationName := fmt.Sprintf("StatisticsExportTemplate_%s.xlsx", id)
//	destinationPath := fmt.Sprintf("./%s", destinationName) // 目标文件夹及新文件名
//	err = ioutil.WriteFile(destinationPath, []byte{}, 0644) // 创建空白目标文件
//	if err != nil {
//		//service.ReturnJson(c, 500, errors.New("无法创建目标文件").Error(), gin.H{})
//		fmt.Println("================== 无法创建目标文件")
//		return
//	}
//	content, err := ioutil.ReadFile(sourcePath) // 读取源文件内容
//	if err != nil {
//		//service.ReturnJson(c, 500, errors.New("无法打开源文件").Error(), gin.H{})
//		fmt.Println("================== 无法打开源文件")
//		return
//	}
//	err = ioutil.WriteFile(destinationPath, content, 0644) // 将源文件内容写入目标文件
//	if err != nil {
//		//service.ReturnJson(c, 500, errors.New("无法写入目标文件").Error(), gin.H{})
//		fmt.Println("================== 无法写入目标文件")
//		return
//	}
//
//	//数据重组
//	rawdata := make(map[string]interface{})
//	err = json.Unmarshal([]byte(taskdata[0]["raw"]), &rawdata)
//	if err != nil {
//		//service.ReturnJson(c, 500, errors.New("无法写入目标文件").Error(), gin.H{})
//		fmt.Println("==================  json.Unmarshal 错误")
//		return
//	}
//
//	for i := 0; i < 100000; i++ {
//		count, err := Clockin{}.StatisticsListExport(i+1, 70, "", "", cast.ToInt(rawdata["starttime"]), cast.ToInt(rawdata["endtime"]), id)
//		if count == 0 && err == nil {
//			break
//		}
//		time.Sleep(10 * time.Second)
//	}
//
//	file := fmt.Sprintf("%s/down?filename=%s", config.InitConfig().Host.Host, destinationName)
//	_, err = db.Exec(fmt.Sprintf("UPDATE `task` SET `status` = 2,`file` = '%s',`utime` = UNIX_TIMESTAMP() WHERE `id` = %s", file, id))
//	if err != nil {
//		fmt.Println("================== status = 3 状态变更失败")
//		return
//	}
//}

func (task Task) TaskTestStatisticsExport(id string) {
	db := communal.Sql()
	defer db.Close()

	taskdata, err := db.QueryString(fmt.Sprintf("select * from `task` where id = %s", id))
	if err != nil {
		return
	}

	_, err = db.Exec(fmt.Sprintf("UPDATE `task` SET `status` = 1,`utime` = UNIX_TIMESTAMP() WHERE `id` = %s", id))
	if err != nil {
		fmt.Println("================== status = 1 状态变更失败")
		return
	}
	//c.Request.Header.Add("ExportIs", "1")
	//c.Request.Header.Add("ExportId", id)

	//创建文件
	fileName := "StatisticsExportTemplate.xlsx"
	sourcePath := "./" + fileName
	// 源文件路径
	destinationName := fmt.Sprintf("StatisticsExportTemplate_%s.xlsx", id)
	destinationPath := fmt.Sprintf("./%s", destinationName) // 目标文件夹及新文件名
	err = ioutil.WriteFile(destinationPath, []byte{}, 0644) // 创建空白目标文件
	if err != nil {
		//service.ReturnJson(c, 500, errors.New("无法创建目标文件").Error(), gin.H{})
		fmt.Println("================== 无法创建目标文件")
		return
	}
	content, err := ioutil.ReadFile(sourcePath) // 读取源文件内容
	if err != nil {
		//service.ReturnJson(c, 500, errors.New("无法打开源文件").Error(), gin.H{})
		fmt.Println("================== 无法打开源文件")
		return
	}
	err = ioutil.WriteFile(destinationPath, content, 0644) // 将源文件内容写入目标文件
	if err != nil {
		//service.ReturnJson(c, 500, errors.New("无法写入目标文件").Error(), gin.H{})
		fmt.Println("================== 无法写入目标文件")
		return
	}

	//数据重组
	rawdata := make(map[string]interface{})
	err = json.Unmarshal([]byte(taskdata[0]["raw"]), &rawdata)
	if err != nil {
		//service.ReturnJson(c, 500, errors.New("无法写入目标文件").Error(), gin.H{})
		fmt.Println("==================  json.Unmarshal 错误")
		return
	}

	rowCell := 2

	//==========================================================================
	for i := 0; i < 10000; i++ {
		count, arow, err := Clockin{}.StatisticsExport(rowCell, i+1, 70, "", cast.ToString(rawdata["department"]), cast.ToInt(rawdata["starttime"]), cast.ToInt(rawdata["endtime"]), id)
		if count == 0 && err == nil {
			break
		}
		rowCell += arow
		time.Sleep(10 * time.Second)
	}
	departmentName := ""

	if cast.ToString(rawdata["department"]) != "" {
		department, err := db.QueryString(fmt.Sprintf("select * from department where id = %s", cast.ToString(rawdata["department"])))
		if err != nil {
			//service.ReturnJson(c, 500, errors.New("无法写入目标文件").Error(), gin.H{})
			fmt.Println("==================  department 错误")
			return
		}
		if len(department) > 0 {
			departmentName = department[0]["name"]
		}
	}

	cstSh, _ := time.LoadLocation("Asia/Shanghai") //上海
	dStime := time.Unix(cast.ToInt64(rawdata["starttime"]), 0).In(cstSh)
	dStimeStr := dStime.Format("20060102")
	eEtime := time.Unix(cast.ToInt64(rawdata["endtime"]), 0).In(cstSh)
	eEtimeStr := eEtime.Format("20060102")
	newFileName := fmt.Sprintf("考勤数据统计%s[%s]%s-%s.xlsx", "-"+departmentName, id, dStimeStr, eEtimeStr)
	err = os.Rename(destinationPath, newFileName)
	if err != nil {
		fmt.Println("================== status = 3 状态变更失败")
		return
	}
	file := fmt.Sprintf("%s/outsourced/down?filename=%s", config.InitConfig().Host.Host, newFileName)
	_, err = db.Exec(fmt.Sprintf("UPDATE `task` SET `status` = 2,`file` = '%s',`utime` = UNIX_TIMESTAMP() WHERE `id` = %s", file, id))
	if err != nil {
		fmt.Println("================== status = 3 状态变更失败")
		return
	}
}

func (task Task) TaskTestDetailedExport(id string) {
	db := communal.Sql()
	defer db.Close()

	taskdata, err := db.QueryString(fmt.Sprintf("select * from `task` where id = %s", id))
	if err != nil {
		return
	}

	_, err = db.Exec(fmt.Sprintf("UPDATE `task` SET `status` = 1,`utime` = UNIX_TIMESTAMP() WHERE `id` = %s", id))
	if err != nil {
		fmt.Println("================== status = 1 状态变更失败")
		return
	}
	//c.Request.Header.Add("ExportIs", "1")
	//c.Request.Header.Add("ExportId", id)

	//创建文件
	fileName := "DetailedExportTemplate.xlsx"
	sourcePath := "./" + fileName
	// 源文件路径
	destinationName := fmt.Sprintf("DetailedExportTemplate_%s.xlsx", id)
	destinationPath := fmt.Sprintf("./%s", destinationName) // 目标文件夹及新文件名
	err = ioutil.WriteFile(destinationPath, []byte{}, 0644) // 创建空白目标文件
	if err != nil {
		//service.ReturnJson(c, 500, errors.New("无法创建目标文件").Error(), gin.H{})
		fmt.Println("================== 无法创建目标文件")
		return
	}
	content, err := ioutil.ReadFile(sourcePath) // 读取源文件内容
	if err != nil {
		//service.ReturnJson(c, 500, errors.New("无法打开源文件").Error(), gin.H{})
		fmt.Println("================== 无法打开源文件")
		return
	}
	err = ioutil.WriteFile(destinationPath, content, 0644) // 将源文件内容写入目标文件
	if err != nil {
		//service.ReturnJson(c, 500, errors.New("无法写入目标文件").Error(), gin.H{})
		fmt.Println("================== 无法写入目标文件")
		return
	}

	//数据重组
	rawdata := make(map[string]interface{})
	err = json.Unmarshal([]byte(taskdata[0]["raw"]), &rawdata)
	if err != nil {
		//service.ReturnJson(c, 500, errors.New("无法写入目标文件").Error(), gin.H{})
		fmt.Println("==================  json.Unmarshal 错误")
		return
	}

	rowCell := 3

	//==========================================================================
	for i := 0; i < 10000; i++ {
		count, arow, err := Clockin{}.DetailedListExport(rowCell, i+1, 70, "", "", cast.ToInt(rawdata["starttime"]), cast.ToInt(rawdata["endtime"]), id)
		if count == 0 && err == nil {
			break
		}
		rowCell += arow
		time.Sleep(10 * time.Second)
	}

	file := fmt.Sprintf("%s/outsourced/down?filename=%s", config.InitConfig().Host.Host, destinationName)
	_, err = db.Exec(fmt.Sprintf("UPDATE `task` SET `status` = 2,`file` = '%s',`utime` = UNIX_TIMESTAMP() WHERE `id` = %s", file, id))
	if err != nil {
		fmt.Println("================== status = 3 状态变更失败")
		return
	}
}

func (task Task) TaskTestStatisticsNotice(id string) {
	db := communal.Sql()
	defer db.Close()

	taskdata, err := db.QueryString(fmt.Sprintf("select * from `task` where id = %s", id))
	if err != nil {
		return
	}

	_, err = db.Exec(fmt.Sprintf("UPDATE `task` SET `status` = 1,`utime` = UNIX_TIMESTAMP() WHERE `id` = %s", id))
	if err != nil {
		fmt.Println("================== status = 1 状态变更失败")
		return
	}
	//c.Request.Header.Add("ExportIs", "1")
	//c.Request.Header.Add("ExportId", id)

	//数据重组
	rawdata := make(map[string]interface{})
	err = json.Unmarshal([]byte(taskdata[0]["raw"]), &rawdata)
	if err != nil {
		//service.ReturnJson(c, 500, errors.New("无法写入目标文件").Error(), gin.H{})
		fmt.Println("==================  json.Unmarshal 错误")
		return
	}

	//==========================================================================
	for i := 0; i < 10000; i++ {
		count, err := Clockin{}.StatisticsNotice(i+1, 30, cast.ToString(rawdata["staff"]), "", cast.ToInt(rawdata["starttime"]), cast.ToInt(rawdata["endtime"]), id)
		if count == 0 && err == nil {
			break
		}
		time.Sleep(10 * time.Second)
	}

	_, err = db.Exec(fmt.Sprintf("UPDATE `task` SET `status` = 2,`utime` = UNIX_TIMESTAMP() WHERE `id` = %s", id))
	if err != nil {
		fmt.Println("================== status = 3 状态变更失败")
		return
	}
}
